<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>组件配置化 | 被删的前端游乐场</title>
    <meta name="generator" content="VuePress 1.8.2">
    
    <meta name="description" content="Just playing around">
    
    <link rel="preload" href="/front-end-playground/assets/css/0.styles.6ad2a9ca.css" as="style"><link rel="preload" href="/front-end-playground/assets/js/app.1e2670bf.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/2.38d016d1.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/3.e3f029cb.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/53.b24af62d.js" as="script">
    <link rel="stylesheet" href="/front-end-playground/assets/css/0.styles.6ad2a9ca.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/front-end-playground/" class="home-link router-link-active"><!----> <span class="site-name">被删的前端游乐场</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/front-end-playground/" class="nav-link">概述</a></div><div class="nav-item"><a href="/front-end-playground/front-end-basic/" class="nav-link router-link-active">前端领域</a></div><div class="nav-item"><a href="/front-end-playground/vue/" class="nav-link">Vue学习</a></div><div class="nav-item"><a href="/front-end-playground/wxapp/" class="nav-link">小程序学习</a></div><div class="nav-item"><a href="/front-end-playground/front-end-others/" class="nav-link">百家齐放</a></div><div class="nav-item"><a href="/front-end-playground/front-end-addon/" class="nav-link">前端的进击</a></div><div class="nav-item"><a href="/front-end-playground/front-end-work/" class="nav-link">前端与工作</a></div><div class="nav-item"><a href="/front-end-playground/faq.html" class="nav-link">FAQ</a></div> <a href="https://github.com/godbasin/front-end-playground" target="_blank" rel="noopener noreferrer" class="repo-link">
    Github
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/front-end-playground/" class="nav-link">概述</a></div><div class="nav-item"><a href="/front-end-playground/front-end-basic/" class="nav-link router-link-active">前端领域</a></div><div class="nav-item"><a href="/front-end-playground/vue/" class="nav-link">Vue学习</a></div><div class="nav-item"><a href="/front-end-playground/wxapp/" class="nav-link">小程序学习</a></div><div class="nav-item"><a href="/front-end-playground/front-end-others/" class="nav-link">百家齐放</a></div><div class="nav-item"><a href="/front-end-playground/front-end-addon/" class="nav-link">前端的进击</a></div><div class="nav-item"><a href="/front-end-playground/front-end-work/" class="nav-link">前端与工作</a></div><div class="nav-item"><a href="/front-end-playground/faq.html" class="nav-link">FAQ</a></div> <a href="https://github.com/godbasin/front-end-playground" target="_blank" rel="noopener noreferrer" class="repo-link">
    Github
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0" style="padding-top:;"><!----> <p class="sidebar-heading"><span>前端架构</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0" style="padding-top:10px;"><div class="kitty-main" data-v-2b653b36><span class="stand" data-v-2b653b36></span> <div class="cat" data-v-2b653b36><div class="body" data-v-2b653b36></div> <div class="head" data-v-2b653b36><div class="ear" data-v-2b653b36></div> <div class="ear" data-v-2b653b36></div></div> <div class="face" data-v-2b653b36><div class="nose" data-v-2b653b36></div> <div class="whisker-container" data-v-2b653b36><div class="whisker" data-v-2b653b36></div> <div class="whisker" data-v-2b653b36></div></div> <div class="whisker-container" data-v-2b653b36><div class="whisker" data-v-2b653b36></div> <div class="whisker" data-v-2b653b36></div></div></div> <div class="tail-container" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36></div></div></div></div></div></div></div></div></div></div> <p class="sidebar-heading open"><span>前端深入理解</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/front-end-playground/front-end-basic/understanding/operation-transform.html" class="sidebar-link">多人协作如何进行冲突处理</a></li><li><a href="/front-end-playground/front-end-basic/understanding/component-communication-with-data-model.html" class="sidebar-link">数据抽离与数据管理</a></li><li><a href="/front-end-playground/front-end-basic/understanding/component-with-configuration.html" aria-current="page" class="active sidebar-link">组件配置化</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/component-with-configuration.html#可配置的数据" class="sidebar-link">可配置的数据</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/component-with-configuration.html#可配置的接口" class="sidebar-link">可配置的接口</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/component-with-configuration.html#可配置的页面" class="sidebar-link">可配置的页面</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/component-with-configuration.html#可配置的应用" class="sidebar-link">可配置的应用</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/component-with-configuration.html#可配置的数据-2" class="sidebar-link">可配置的数据</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/component-with-configuration.html#可配置的样式" class="sidebar-link">可配置的样式</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/component-with-configuration.html#可配置的展示" class="sidebar-link">可配置的展示</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/component-with-configuration.html#可配置的功能" class="sidebar-link">可配置的功能</a></li></ul></li><li><a href="/front-end-playground/front-end-basic/understanding/component-with-itself.html" class="sidebar-link">一个组件的自我修养</a></li><li><a href="/front-end-playground/front-end-basic/understanding/app-component-isolation.html" class="sidebar-link">页面区块化与应用组件化</a></li><li><a href="/front-end-playground/front-end-basic/understanding/template-engine.html" class="sidebar-link">前端模板引擎</a></li><li><a href="/front-end-playground/front-end-basic/understanding/dialogue-abstraction.html" class="sidebar-link">对话抽象</a></li><li><a href="/front-end-playground/front-end-basic/understanding/data-driven-or-event-driven.html" class="sidebar-link">前端思维转变--从事件驱动到数据驱动</a></li><li><a href="/front-end-playground/front-end-basic/understanding/web-browser-render.html" class="sidebar-link">浏览器是如何进行页面渲染的</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0" style="padding-top:;"><!----> <p class="sidebar-heading"><span>前端入门</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><p>配置化思想，其实可以在很多的地方使用。很多时候，我们在设计接口、应用、数据等情况下，配置化的方式可以允许我们获得更高的自由度。这里我们简单讲讲组件的配置化吧。</p> <h1 id="配置化思想"><a href="#配置化思想" class="header-anchor">#</a> 配置化思想</h1> <h2 id="可配置的数据"><a href="#可配置的数据" class="header-anchor">#</a> 可配置的数据</h2> <p>数据的配置，或许大家会比较熟悉。像一些静态数据呀，或者说我们很多的管理端都是用来进行数据配置的。</p> <h3 id="应用中的可配置数据"><a href="#应用中的可配置数据" class="header-anchor">#</a> 应用中的可配置数据</h3> <p>最常见的数据配置，大概是应用里面的配置，文案呀、说明等，为此我们有了运营这样的职位。常见的方式，则是搭起一整套的运营管理平台，一些简单的文字或是数据，则可以通过平台进行配置。</p> <h3 id="代码中的可配置数据"><a href="#代码中的可配置数据" class="header-anchor">#</a> 代码中的可配置数据</h3> <p>有些时候，我们也会在代码里面放置一些可配置的数据。例如说，这个需求需要查询一周的数据，常见的做法是将天数配置为 7 天：</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">const</span> <span class="token constant">QUERY_DAY_NUM</span> <span class="token operator">=</span> <span class="token number">7</span><span class="token punctuation">;</span>
</code></pre></div><p>这样，当需要在紧急情况支持其他天数（五一、国庆、过年能假期）的时候，我们就可以只需要改动这里就好啦。</p> <h3 id="文件里的可配置数据"><a href="#文件里的可配置数据" class="header-anchor">#</a> 文件里的可配置数据</h3> <p>有些情况下，一些影响逻辑的配置数据，要是直接写到代码里，在调整的时候通常需要重新打包部署，这样情况下开销大、效率低。</p> <p>所以在一些时候，我们会把这样的可配置数据，单独写到某个文件里维护。当需要调整的时候，只需要下发一个配置文件就好啦。</p> <h2 id="可配置的接口"><a href="#可配置的接口" class="header-anchor">#</a> 可配置的接口</h2> <p>关于接口的配置化，目前来说见过的不是特别多。毕竟目前来说，我们的很多数据和接口并不是简单的增删查改这样的功能，很多时候还需要在接口返回前后，做一系列的逻辑处理。</p> <p>简单地说，很多的业务接口场景复用性不高，前后端除去协议、基础规范的定义之后，很少再能进行更深层次的抽象，导致接口配置化的改造成本较大。</p> <p>配置化的实现有两点很重要的东西：<strong>规范</strong>和<strong>解决方案</strong>。如果说目前较好的从前端到后台的规范，可能 <a href="https://graphql.cn/" target="_blank" rel="noopener noreferrer">GrapgQL<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 和 Restful ，大家不熟悉的也可以去看看啦。</p> <p>当然，或许有些团队已经实现了，也希望尽快能看到一些相关的解决方案啦。</p> <h2 id="可配置的页面"><a href="#可配置的页面" class="header-anchor">#</a> 可配置的页面</h2> <p>页面的配置化，可能也已经不少见了吧。像我刚出道的时候，也写过<a href="http://o907xb1mi.bkt.clouddn.com/index.html" target="_blank" rel="noopener noreferrer">一个拖拽的 demo<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>，虽然现在光想想那时候的 jQuery 代码就惨不忍睹，不过当时还是觉得自己挺牛逼的。</p> <p>有些时候，一些页面比较简单，里面的板块、功能比较相似，可能文案不一致、模块位置调整了、颜色改变等等。虽然说复制粘贴再改一改，很多时候也能满足要求，但是配置化的思想，就是要把重复性的工作交给机器呀。</p> <p>这种页面的配置，基本上有两种实现方式：</p> <ol><li>配置后生成静态页面的代码，直接加载生成的页面代码。</li> <li>写通用的配置化逻辑，在加载页面的时候拉取配置数据，动态生成页面。</li></ol> <p>基于 SEO 和实现复杂度各种情况，第一种方式大概是目前比较常用的，第二种的实现难度会稍微大一些，同时对于 SEO 与单页应用有着相同的困境。</p> <p>第一种方式，很多适用于一些移动端的模版页面开发，例如简单的活动页面、商城页面等等。</p> <p>第二种的话，更多的是一些管理平台的实现，毕竟大多数都是增删查改，形式无非列表、表单和菜单等。之前我也捣鼓过一小会的 Angular 表单、列表等配置，可以看看<a href="http://otaj284f8.bkt.clouddn.com/#/home/custom-app" target="_blank" rel="noopener noreferrer">Angular 自定义页面<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>和这个<a href="http://p2n7500x0.bkt.clouddn.com/index.html" target="_blank" rel="noopener noreferrer">Angular2 Schema Form Exemple<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>。嗯，可能有些 bug，don't mind don't mind~</p> <h2 id="可配置的应用"><a href="#可配置的应用" class="header-anchor">#</a> 可配置的应用</h2> <p>可配置的应用，大概更多地是从业务和应用设计的角度出发。当我们设计一个应用的时候，页面是活动的、可变的、可配置的，这些都是需要考虑到的地方。</p> <p>当然，如果说涉及到代码实现的话，那大概与上面的相关。配置化的思想，其实或许不局限于代码、工程和我们的工作，甚至我们完全可以拓展至我们的生活中。</p> <h1 id="组件配置化"><a href="#组件配置化" class="header-anchor">#</a> 组件配置化</h1> <p>那么这里我们来讲一下简单的配置化组件的实现把。关于组件的封装，我们在<a href="/front-end-playground/front-end-basic/understanding/component-with-itself.html">《一个组件的自我修养》</a>一文也讲述过。</p> <p>下面的组件，我们同样拿这样一个卡片组件来作为例子吧。</p> <p><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/1524133892%281%29.jpg" alt="image"></p> <h2 id="可配置的数据-2"><a href="#可配置的数据-2" class="header-anchor">#</a> 可配置的数据</h2> <p>首先是数据的配置，这大概是最基础的，当我们在封装组件的时候，很多数据都是通过作用域内的变量来动态绑定的，例如 Vue 里面则是<code>data</code>、<code>props</code>、<code>computed</code>等维护 scope 内的数据绑定。</p> <p>作为一个卡片，内容是从外面注入的，所以我们可以通过 <code>props</code> 来获取：</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h2</span><span class="token punctuation">&gt;</span></span>{{model.question}}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h2</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>model.withImage<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">:url</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>model.imageUrl<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>{{model.content}}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">@click</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>likeIt()<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>点赞<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">@click</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>keepIt()<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>收藏<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>comment in model.comments<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>{{comment}}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
  <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
    name<span class="token operator">:</span> <span class="token string">&quot;my-card&quot;</span><span class="token punctuation">,</span>
    props<span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token comment">// 传入数据</span>
      model<span class="token operator">:</span> <span class="token punctuation">{</span>
        type<span class="token operator">:</span> Object<span class="token punctuation">,</span>
        <span class="token function-variable function">default</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token punctuation">{</span>
        isContextShown<span class="token operator">:</span> <span class="token boolean">false</span>
      <span class="token punctuation">}</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    methods<span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token function">likeIt</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token function">keepIt</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function">mounted</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>这里只展示简单的方式，我们会这样使用：</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>my-card</span> <span class="token attr-name">:model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>cardModel<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>my-card</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h2 id="可配置的样式"><a href="#可配置的样式" class="header-anchor">#</a> 可配置的样式</h2> <p>样式的配置，通常是通过<code>class</code>来实现的。其实这更多地是对样式的配置化设计，与我们的 HTML 和 Javascript 关系则比较少。</p> <p>样式的配置，需要我们考虑 CSS 的设计，通常来说我们有两种方式：</p> <ol><li>根据子元素匹配，来描述 CSS。</li> <li>根据子 class 匹配，来描述 CSS。</li></ol> <h3 id="根据子元素配置-css"><a href="#根据子元素配置-css" class="header-anchor">#</a> 根据子元素配置 CSS</h3> <p>这是以前比较常用的一种方式，简单地说，就是通过 CSS 匹配规则中的父子元素匹配，来完成我们的样式设计。</p> <p>例如，我们有个模块：</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>my-dialog<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>header</span><span class="token punctuation">&gt;</span></span>I am header.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>header</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>section</span><span class="token punctuation">&gt;</span></span>
    blablablabla...
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>section</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>footer</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">&gt;</span></span>Submit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>footer</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>样式则会这样设计：</p> <div class="language-CSS extra-class"><pre class="language-css"><code><span class="token selector">.my-dialog</span> <span class="token punctuation">{</span>
  <span class="token property">background</span><span class="token punctuation">:</span> white<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.my-dialog &gt; header</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token selector">.my-dialog &gt; section</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token selector">.my-dialog &gt; footer</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</code></pre></div><p>或者说用 LESS 或是 SASS：</p> <div class="language-LESS extra-class"><pre class="language-less"><code><span class="token selector">.my-dialog</span> <span class="token punctuation">{</span>
  <span class="token property">background</span><span class="token punctuation">:</span> white<span class="token punctuation">;</span>
  <span class="token selector">&gt; header</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
  <span class="token selector">&gt; section</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
  <span class="token selector">&gt; footer</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>通过这种方式设计，或许我们在写代码的时候会稍微方便些，但是在维护上面很容易踩坑。曾经我也喜欢这种方式写，后来在一次次的 DOM 结构调整过程中，差点掉坑里出不来，于是乎后面慢慢改用第二种方式。</p> <h3 id="根据子-class-配置-css"><a href="#根据子-class-配置-css" class="header-anchor">#</a> 根据子 class 配置 CSS</h3> <p>其实相对于匹配简单的父子和后代元素关系，使用 class 来辅助匹配，则可以解决 DOM 调整的时候带来的问题。</p> <p>这里我们使用 BEM 作为例子来解释下大概的想法吧：</p> <p><strong>BEM</strong>
BEM 的意思就是块（block）、元素（element）、修饰符（modifier），是一种前端命名方法论。更多的大家可以去谷歌或者百度下。</p> <p>简单说，我们写 CSS 的时候就是这样的：</p> <div class="language-CSS extra-class"><pre class="language-css"><code><span class="token selector">.block</span><span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token selector">.block__element</span><span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token selector">.block--modifier</span><span class="token punctuation">{</span><span class="token punctuation">}</span>
</code></pre></div><ul><li>block：可以与组件和模块对应的命名，如 card、dialog 等</li> <li>element：元素，如 header、footer 等</li> <li>modifier：修饰符，可视作状态等描述，如 actived、closed 等</li></ul> <p>这样的话，我们上述的代码则会变成：</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>my-dialog<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>header</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>my-dialog__header<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>I am header.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>header</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>section</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>my-dialog__section<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    blablablabla...
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>section</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>footer</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>my-dialog__footer<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>my-dialog__btn--inactived<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>Submit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>footer</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>搭配 LESS 的话，其实样式还是挺好写的：</p> <div class="language-LESS extra-class"><pre class="language-less"><code><span class="token selector">.my-dialog</span> <span class="token punctuation">{</span>
  <span class="token property">background</span><span class="token punctuation">:</span> white<span class="token punctuation">;</span>
  <span class="token selector">&amp;__header</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
  <span class="token selector">&amp;__section</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
  <span class="token selector">&amp;__footer</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
  <span class="token selector">&amp;__btn</span> <span class="token punctuation">{</span>
    &amp;<span class="token operator">-</span><span class="token operator">-</span>inactived
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>Emmmmmm。。其实大家看了下，就发现这样的弊端了，这样我们在写 HTML 的时候，需要耗费很多的时间来写这些 class 名字，更惨的是，当我们需要切换某个元素状态的时候，判断条件会变得很长，像：</p> <div class="language-HTML extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">:class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>isActived ? <span class="token punctuation">'</span>my-dialog__btn--actived<span class="token punctuation">'</span> : <span class="token punctuation">'</span>my-dialog__btn--inactived<span class="token punctuation">'</span><span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>Submit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>简直惨不忍睹。当然我们也可以把修饰符部分脱离，这样使用：</p> <div class="language-HTML extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>my-dialog__btn<span class="token punctuation">&quot;</span></span> <span class="token attr-name">:class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>isActived ? <span class="token punctuation">'</span>actived<span class="token punctuation">'</span> : <span class="token punctuation">'</span>inactived<span class="token punctuation">'</span><span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>Submit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>这样会稍微好一些。BEM 的优势和弊端也都是很明显的，大家也可以根据具体的团队规模、项目规模、使用场景等，来决定要怎么设计。</p> <p>当然，如今很多框架都支持样式的作用域，通常是通过在 class 里添加随机 MD5 等，来保持局部作用域的 class 样式。常见的话，我们是搭配第一和第二种方式一起使用的。</p> <h2 id="可配置的展示"><a href="#可配置的展示" class="header-anchor">#</a> 可配置的展示</h2> <p>可配置的展示，更多时候是指某些模块是否展示、展示的样式又是如何等。</p> <p>例如，我们需要一个对话框，其头部、正文文字、底部按钮等功能都可支持配置：</p> <div class="language-HTML extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>my-dialog<span class="token punctuation">&quot;</span></span> <span class="token attr-name">:class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>{<span class="token punctuation">'</span>show<span class="token punctuation">'</span>: isShown}<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>header</span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>model.title<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>{{model.title}}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>header</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>section</span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>model.content<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>{{model.content}}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>section</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>footer</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>button in model.buttons<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>{{button.text}}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>footer</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>我们可以通过<code>model.title</code>来控制是否展示头部，可以通过<code>model.buttons</code>来控制底部按钮的数量和文字。</p> <p>这只是最简单的实例，我们甚至可以通过配置，来控制出完全不一样的展示效果。搭配样式的配置，更是能让组件出神入化。当然，很多时候我们组件的封装是需要与业务设计相关，这样维护性能也会稍微好一些，这些前面也都有说到过。</p> <h2 id="可配置的功能"><a href="#可配置的功能" class="header-anchor">#</a> 可配置的功能</h2> <p>功能的配置，其实很多也与展示的配置相关。但是我们有些与业务相关的功能，则可以结合展示、功能来定义这样的配置。</p> <p>举个例子，我们的这个卡片可以是视频、图片、文字的卡片：</p> <ul><li>视频：点击播放</li> <li>图片：点击新窗口查看</li> <li>文字：点击无效果</li></ul> <p>这种时候，我们可以两种方式：</p> <ol><li>每个功能模块自己控制，同时通过配置控制哪个功能模块的展示。</li> <li>模块展示会有些耦合，但在点击事件里，根据配置来进行不同的事件处理，获取不同的效果。</li></ol> <p>对应维护性和可读性来说，第一种方式会获得更好的效果。如果问什么情况下会用到第二种，唔。。。大概是同样的呈现效果，在不同场景下的逻辑功能不一样时，使用比较方便吧。</p> <p>功能配置化这块就不过多描述啦，毕竟这块需要与业务场景密切结合，大家更多地可以思考下，自己的项目中，是否可以有调整的空间，来使得整体的项目更好维护呢？</p> <h1 id="结束语"><a href="#结束语" class="header-anchor">#</a> 结束语</h1> <p>我们讲述了很多的配置化场景，也针对组件来详细描述了一些配置化的方向和方式。随着科技越来越发达，很多简单和重复性的事情我们可以交给机器去做，这就需要我们把相似的部分提取出来抽象封装，把可变的部分结合配置来高效地调整。<br>
抽象封装和配置化的搭配，其实能获得很不错的效果，我们在对一些事物的认知上，也能进行更深层次的概括和思考。</p></div> <!----> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/godbasin/front-end-playground/edit/sourcecode/docs/front-end-basic/understanding/component-with-configuration.md" target="_blank" rel="noopener noreferrer">帮阿猪改善此页面！</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <!----> <blockquote>部分文章中使用了一些网站的截图，如果涉及侵权，请告诉我删一下谢谢~</blockquote> <div style="margin-top:30px;"><div class="el-row" style="margin-left:-10px;margin-right:-10px;"><div class="el-col el-col-24 el-col-sm-0 el-col-md-2 el-col-lg-4" style="padding-left:10px;padding-right:10px;display:block;"><div style="width:1px;height:1px;"></div></div> <div class="el-col el-col-24 el-col-sm-24 el-col-md-18 el-col-lg-16" style="padding-left:10px;padding-right:10px;"><div class="el-card box-card is-always-shadow"><div class="el-card__header"><div class="clearfix"><span>温馨提示喵</span></div></div><div class="el-card__body"> <div class="el-row" style="margin-left:-10px;margin-right:-10px;"><div class="el-col el-col-24 el-col-xs-24 el-col-sm-12" style="padding-left:10px;padding-right:10px;"><div class="el-image"><div class="image-slot"><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/assets/img/loading.gif" style="width:100%;"></div><!----></div></div> <div class="el-col el-col-24 el-col-xs-24 el-col-sm-12" style="padding-left:10px;padding-right:10px;"><div class="copyright-text"><div>本文版权归作者所有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。</div> <div>出处：被删的前端游乐场</div> <div>作者：<a href="https://github.com/godbasin" target="_blank">被删</a></div></div></div></div></div></div></div></div></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/front-end-playground/front-end-basic/understanding/component-communication-with-data-model.html" class="prev">
          数据抽离与数据管理
        </a></span> <span class="next"><a href="/front-end-playground/front-end-basic/understanding/component-with-itself.html">
          一个组件的自我修养
        </a>
        →
      </span></p></div>  <div class="gitalk-container theme-default-content"><div id="gitalk-container" class="content"></div></div></main> <div id="kitty-container"><span><div role="tooltip" id="el-popover-6874" aria-hidden="true" class="el-popover el-popper" style="width:undefinedpx;display:none;"><!----><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/2code2.jpg" class="image"> <div class="text">牡羊猪的猫粮罐</div> </div><span class="el-popover__reference-wrapper"><div id="kitty" style="background:url(https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/assets/img/kitty0.svg);"></div></span></span> <div class="el-dialog__wrapper" style="display:none;"><div role="dialog" aria-modal="true" aria-label="牡羊猪是这样渐渐胖成猪的喵（点击图片可以切换噢）" class="el-dialog" style="margin-top:15vh;"><div class="el-dialog__header"><span class="el-dialog__title">牡羊猪是这样渐渐胖成猪的喵（点击图片可以切换噢）</span><button type="button" aria-label="Close" class="el-dialog__headerbtn"><i class="el-dialog__close el-icon el-icon-close"></i></button></div><!----><!----></div></div></div></div><div class="global-ui"></div></div>
    <script src="/front-end-playground/assets/js/app.1e2670bf.js" defer></script><script src="/front-end-playground/assets/js/2.38d016d1.js" defer></script><script src="/front-end-playground/assets/js/3.e3f029cb.js" defer></script><script src="/front-end-playground/assets/js/53.b24af62d.js" defer></script>
  </body>
</html>
